package com.yike.user.utils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.yike.common.exception.BusinessException;
import com.yike.common.redis.RedisUtil;
import com.yike.common.tool.HttpsRequestUtil;
import com.yike.common.tool.StringUtil;
import com.yike.user.param.GetAppCodeParam;
import com.yike.user.vo.wx.WxAccessTokenVo;
import com.yike.user.vo.wx.WxAppLoginVo;
import com.yike.user.vo.wx.WxPhoneVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

/**
 * @author Sakura
 * @date 2024/8/22 11:04
 * 微信小程序工具类
 */
@Component
@Slf4j
public class WxMchAppUtil {

    @Value("${wx.app.mch-appid}")
    private String appid;

    @Value("${wx.app.mch-secret}")
    private String secret;

    // 获取授权token
    private static final String GET_TOKEN = "https://api.weixin.qq.com/cgi-bin/token";

    // 获取授权用户信息URL
    private static final String JS_CODE_2_SESSION_URL = "https://api.weixin.qq.com/sns/jscode2session";

    private static final String WX_MCH_APP_ACCESS_TOKEN = "wx_mch_app_access_token";

    // 获取授权手机号URL
    private static final String GET_USER_PHONE_NUMBER_URL = "https://api.weixin.qq.com/wxa/business/getuserphonenumber";

    // 获取小程序码URL
    private static final String GET_APP_CODE_URL = "https://api.weixin.qq.com/wxa/getwxacode";

    // 获取不受限制的小程序码
    private static final String GET_UNLIMITED_APP_CODE_URL = "https://api.weixin.qq.com/wxa/getwxacodeunlimit";

    private static final String GET_APP_QR_CODE_URL = "https://api.weixin.qq.com/cgi-bin/wxaapp/createwxaqrcode";

    @Autowired
    private RedisUtil redisUtil;

    // 获取授权凭证
    public String getAccessToken() {
        // 优先从Redis获取，没有再调接口
        // 如果Redis里面有则直接取Redis里面的
        if (redisUtil.hasKey(WX_MCH_APP_ACCESS_TOKEN)) {
            log.info(redisUtil.get(WX_MCH_APP_ACCESS_TOKEN).toString());
            return redisUtil.get(WX_MCH_APP_ACCESS_TOKEN).toString();
        }
        // 拼接请求参数
        StringBuilder strUrl = new StringBuilder();
        strUrl.append(GET_TOKEN)
                .append("?grant_type=client_credential")
                .append("&appid=").append(appid)
                .append("&secret=").append(secret);
        try {
            String resultStr = HttpsRequestUtil.sendGetRequest(strUrl.toString());
            log.info("【微信小程序获取授权凭证】：返回结果：" + resultStr);
            WxAccessTokenVo wxAccessTokenVo = JSON.parseObject(resultStr, WxAccessTokenVo.class);
            if (StringUtil.isBlank(wxAccessTokenVo.getAccess_token())) {
                throw new BusinessException("微信小程序获取授权凭证异常");
            }

            //官方 access_token expires_in 为 2个小时, 这里设置 100分钟
            redisUtil.set(WX_MCH_APP_ACCESS_TOKEN, wxAccessTokenVo.getAccess_token(), 100 * 60);

            return wxAccessTokenVo.getAccess_token();
        } catch (Exception e) {
            log.info("【微信小程序获取授权凭证】：获取异常：" + e.getMessage());
            e.printStackTrace();
            throw new BusinessException("微信小程序获取授权凭证异常");
        }
    }

    // 小程序授权登录
    public WxAppLoginVo login(String code) {
        // 拼接请求参数
        StringBuilder strUrl = new StringBuilder();
        strUrl.append(JS_CODE_2_SESSION_URL)
                .append("?appid=").append(appid)
                .append("&secret=").append(secret)
                .append("&js_code=").append(code)
                .append("&grant_type=authorization_code");
        try {
            String resultStr = HttpsRequestUtil.sendGetRequest(strUrl.toString());
            log.info("【微信小程序登录】：登录返回结果：" + resultStr);
            WxAppLoginVo wxAppLoginVo = JSON.parseObject(resultStr, WxAppLoginVo.class);
            if (wxAppLoginVo.getErrcode() != null && wxAppLoginVo.getErrcode() != 0) {
                log.info("【微信小程序登录】：登录失败，错误码：" + wxAppLoginVo.getErrcode() + "  " + wxAppLoginVo.getErrmsg());
                throw new BusinessException(wxAppLoginVo.getErrmsg());
            }
            return wxAppLoginVo;
        } catch (Exception e) {
            log.info("【微信小程序登录】：登录异常：" + e.getMessage());
            e.printStackTrace();
            throw new BusinessException("微信小程序登录异常");
        }
    }

    // 获取微信授权手机号
    public WxPhoneVo getWxPhone(String code) {
        // 先要获取access_token
        String accessToken = getAccessToken();
        // 拼接请求参数
        StringBuilder strUrl = new StringBuilder();
        strUrl.append(GET_USER_PHONE_NUMBER_URL)
                .append("?access_token=")
                .append(accessToken);

        // 封装请求参数到body
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("code", code);

        try {
            String resultStr = HttpsRequestUtil.sendPostRequest(strUrl.toString(), jsonObject.toJSONString());
            log.info("【微信小程序获取手机号】：获取手机号返回结果：" + resultStr);
            WxPhoneVo wxPhoneVo = JSON.parseObject(resultStr, WxPhoneVo.class);
            if (wxPhoneVo.getErrcode() != null && wxPhoneVo.getErrcode() != 0) {
                log.info("【微信小程序获取手机号】：获取手机号失败，错误码：" + wxPhoneVo.getErrcode() + "  " + wxPhoneVo.getErrmsg());
                throw new BusinessException(wxPhoneVo.getErrmsg());
            }
            return wxPhoneVo;
        } catch (Exception e) {
            log.info("【微信小程序获取手机号】：获取手机号异常：" + e.getMessage());
            e.printStackTrace();
            throw new BusinessException("微信小程序获取手机号异常");
        }
    }

    // 获取小程序码
    public byte[] getAppCode(GetAppCodeParam getAppCodeParam) {
        // 先要获取access_token
        String accessToken = getAccessToken();
        // 拼接请求参数
        StringBuilder strUrl = new StringBuilder();
        strUrl.append(GET_APP_CODE_URL)
                .append("?access_token=")
                .append(accessToken);

        // 封装请求参数到body
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("path", getAppCodeParam.getPath());
        if (StringUtil.isNotBlank(getAppCodeParam.getEnvVersion())) {
            jsonObject.put("env_version", getAppCodeParam.getEnvVersion());
        }
        if (getAppCodeParam.getWidth() != null) {
            jsonObject.put("width", getAppCodeParam.getWidth());
        }
        if (getAppCodeParam.getIsHyaline() != null) {
            jsonObject.put("is_hyaline", getAppCodeParam.getIsHyaline());
        }

        try {
            return HttpsRequestUtil.sendPostReturnByte(strUrl.toString(), jsonObject.toJSONString());
        } catch (Exception e) {
            log.info("【微信小程序获取小程序码】：获取小程序码异常：" + e.getMessage());
            e.printStackTrace();
            throw new BusinessException("微信小程序获取小程序码异常");
        }
    }

    // 获取无限制的小程序码
    public byte[] getUnlimitedAppCode(GetAppCodeParam getAppCodeParam) {
        // 先要获取access_token
        String accessToken = getAccessToken();
        // 拼接请求参数
        StringBuilder strUrl = new StringBuilder();
        strUrl.append(GET_UNLIMITED_APP_CODE_URL)
                .append("?access_token=")
                .append(accessToken);

        // 封装请求参数到body
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("scene", getAppCodeParam.getScene());
        if (StringUtil.isNotBlank(getAppCodeParam.getPage())) {
            jsonObject.put("page", getAppCodeParam.getPage());
        }
        if (StringUtil.isNotBlank(getAppCodeParam.getEnvVersion())) {
            jsonObject.put("env_version", getAppCodeParam.getEnvVersion());
        }
        if (getAppCodeParam.getWidth() != null) {
            jsonObject.put("width", getAppCodeParam.getWidth());
        }
        if (getAppCodeParam.getIsHyaline() != null) {
            jsonObject.put("is_hyaline", getAppCodeParam.getIsHyaline());
        }
        if (getAppCodeParam.getCheckPath() != null) {
            jsonObject.put("check_path", getAppCodeParam.getCheckPath());
        }

        try {
            return HttpsRequestUtil.sendPostReturnByte(strUrl.toString(), jsonObject.toJSONString());
        } catch (Exception e) {
            log.info("【微信小程序获取不限制小程序码】：获取不限制小程序码异常：" + e.getMessage());
            e.printStackTrace();
            throw new BusinessException("微信小程序获取不限制小程序码异常");
        }
    }

    // 获取小程序二维码
    public byte[] getAppQRCode(GetAppCodeParam getAppCodeParam) {
        // 先要获取access_token
        String accessToken = getAccessToken();
        // 拼接请求参数
        StringBuilder strUrl = new StringBuilder();
        strUrl.append(GET_APP_QR_CODE_URL)
                .append("?access_token=")
                .append(accessToken);

        // 封装请求参数到body
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("path", getAppCodeParam.getPath());
        if (getAppCodeParam.getWidth() != null) {
            jsonObject.put("width", getAppCodeParam.getWidth());
        }

        try {
            return HttpsRequestUtil.sendPostReturnByte(strUrl.toString(), jsonObject.toJSONString());
        } catch (Exception e) {
            log.info("【微信小程序获取小程序二维码】：获取小程序二维码异常：" + e.getMessage());
            e.printStackTrace();
            throw new BusinessException("微信小程序获取小程序二维码异常");
        }
    }
}
